home *** CD-ROM | disk | FTP | other *** search
- _IPX: THE GREAT COMMUNICATOR_
- by Rahner James
-
- [LISTING ONE]
-
- ; ***************************************************************************
- ; * Title: ESRS.ASM -- by Rahner James
- ; * Copyright (c) January 1991, Ryu Consulting, 916/722-1939
- ; * File contains default Event Service Routine for listening & talking packets
- ; ****************************************************************************
-
- _ESRS_ASM_ equ 1
- ifdef LARGEMODEL
- .model large,c
- else
- .model small,c
- endif
- ADDRESS_S struct
- network dw ?,? ; Network number
- node dw 3 dup(?); Node address on that network
- socket dw ? ; Socket number on that node
- ADDRESS_S ends
- IPX_PACKET_S struct
- next dd ? ; Used by IPX/SPX when the ECB is active
- function dd ? ; Called after packet sent/recd, called ESR
- in_use db ? ; Set to !0 by IPX/SPX when packet is in use
- completion_code db ? ; Set by XPX after packet task is complete
- socket dw ? ; Socket to use for this ECB
- IPX_work dd ? ; Workspace used internally by IPX
- driver_work dd ?,?,? ; Workspace used internally by IPX driver
- dest_address db 6 dup(?); Destination address for packet
- fragment_count dw ? ; Fragments descriptors that follow
- hdr dd ? ; -> IPX/SPX packet descriptor to use
- size_hdr dw ? ; Size of the IPX(30) or SPX(42) descriptor
- buffer_ptr dd ? ; -> data buffer to use for transmission/reception
- buffer_size dw ? ; Number of bytes in that buffer
- next_allocated dd ? ; -> next allocated packet structure
- next_sibling dd ? ; -> next packet for stream and condition
- parent dd ? ; -> parent stream definition packet
- default_buffer dd ? ; -> default buffer to use for IPX or SPX
- default_size dw ? ; Size of the default buffer
- done_flag dd ? ; Set by the ESR with the completion code
-
- checksum dw ? ; Dummy checksum of 30-byte packet header
- packet_length dw ? ; Length of complete IPX packet
- control db ? ; Transport control byte for internet bridges
- packet_type db ? ; Packet type: IPX(4)/SPX(5)
-
- dest_network dd ? ; Destination network address
- dest_node db 6 dup(?); Destination node address
- dest_socket dw ? ; Destination socket
-
- src_network dd ? ; Source network address
- src_node db 6 dup(?); Source node address
- src_socket dw ? ; Source socket
- IPX_PACKET_S ends
- XPX_STREAM_S struct
- next dd ? ; -> next stream structure opened
- first_allocated dd ? ; -> first allocated packet for handle
- last_allocated dd ? ; -> last allocated packet for handle
- first_unread dd ? ; -> first unread packet
- last_unread dd ? ; -> last unread packet in the list
- first_free dd ? ; -> first packet available for talking
- first_error dd ? ; -> first packet encountering an error
- last_error dd ? ; -> last packet encountering an error
-
- dest_network dd ? ; Destination network address
- dest_node db 6 dup(?); Destination node address
- dest_socket dw ? ; Destination socket
- local_target db 6 dup(?); Node address of local target for dest
- connection_ID dw ? ; Connection ID used for SPX
- total_talkers dw ? ; Number of talkers for this stream
- total_listeners dw ? ; Number of listeners for this stream
- unread_count dw ? ; Number of packets unread by app
- free_count dw ? ; Number of packets ready for talking
- maximum_unread dw ? ; Maximum number of unread packets
- error_count dw ? ; Number of unprocessed error packets
-
- total_transmissions dd ? ; Number of transmissions performed
- total_receptions dd ? ; Number of receptions performed
- total_errors dd ? ; Number of errors encountered
- XPX_STREAM_S ends
- .data
- extern _Ignore_Nomatch:byte, _Our_Address:word, IPX_Vector:dword,
- _First_Stream:dword
- extern _First_Nomatch:dword, _Last_Nomatch:dword, _Total_Nomatchs:word
- .code
- Last_Broad_Ptr dw 0,0 ; -> last checked broadcast stream
-
- ; ****************************************************************************
- ; * void far TALK_ESR( void ) -- Event Service Routine (ESR) for IPX
- ; * functions and their talking packets
- ; * Given: AL = 0 if AES called this ESR, 0xff if this is a normal event
- ; * ES:SI -> ECB that just finished talking
- ; * Returns: Packet either glued onto the free list or the error list
- ; * Note: Interrupts are enabled at this point and should stay that way
- ; ****************************************************************************
- talk_esr proc far
- ; * See if we need to set the done flag
- lds bx, es:[si].IPX_PACKET_S.done_flag ; DS:BX -> process done flag
- mov cl, es:[si].IPX_PACKET_S.completion_code
- mov ax, ds
- or ax, bx
- jz @F ; If DS:BX -> NULL, just skip it
- mov [bx], cl ; Set the flag with our completion code
- mov word ptr es:[si].IPX_PACKET_S.done_flag, 0 ; Make it NULL
- mov word ptr es:[si].IPX_PACKET_S.done_flag+2, 0
- ; * Check whether the packet goes in the error list or the free list
- @@: lds bx, es:[si].IPX_PACKET_S.parent ; DS:BX -> parent structure
- or cl, cl ; See if we got a transmission error
- jnz talk20_esr ; Jump if we got one
- ; * Here's where we process the good transmissions
- add word ptr [bx].XPX_STREAM_S.total_transmissions, 1
- adc word ptr [bx].XPX_STREAM_S.total_transmissions+2, 0
- inc [bx].XPX_STREAM_S.free_count;
- mov cx, word ptr [bx].XPX_STREAM_S.first_free ; DX:CX -> first free
- mov dx, word ptr [bx].XPX_STREAM_S.first_free+2
- mov word ptr [bx].XPX_STREAM_S.first_free, si
- mov word ptr [bx].XPX_STREAM_S.first_free+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, cx
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, dx
- talk10_esr:
- ret
- ; * Here's where we take care of our challenged packets
- talk20_esr:
- add word ptr [bx].XPX_STREAM_S.total_errors, 1
- adc word ptr [bx].XPX_STREAM_S.total_errors+2, 0
- inc [bx].XPX_STREAM_S.error_count
- mov cx, word ptr [bx].XPX_STREAM_S.last_error ; DX:CX ->last error
- mov dx, word ptr [bx].XPX_STREAM_S.last_error+2
- mov word ptr [bx].XPX_STREAM_S.last_error, si ; Set new last error
- mov word ptr [bx].XPX_STREAM_S.last_error+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F
- mov word ptr [bx].XPX_STREAM_S.first_error, si ;Set new first error
- mov word ptr [bx].XPX_STREAM_S.first_error+2, es
- ret
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si ; Point old end
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
- talk_esr endp
-
- ; ****************************************************************************
- ; * void far LISTEN_ESR( void ) -- Event Service Routine (ESR) for IPX
- ; * functions and their listening packets
- ; * Given: AL = 0 if AES called this ESR, 0xff if this is a normal event
- ; * ES:SI -> ECB that just got something
- ; * Returns: Packet put at the end of the unread packet list of the stream it
- ; * was intended for.
- ; * Note: Interrupts are enabled at this point and should stay that way. This
- ; * packet may not be put with its parent if there are multiple parents
- ; * associated with one socket
- ; ****************************************************************************
- listen_esr proc far
- mov ax, @Data ; DS = our data segment
- mov ds, ax
- ; * First see if we sent it as a broadcast and it got back to us
- mov ax, _Our_Address.ADDRESS_S.node+4
- cmp word ptr es:[si].IPX_PACKET_S.src_node+4, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.node+2
- cmp word ptr es:[si].IPX_PACKET_S.src_node+2, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.node
- cmp word ptr es:[si].IPX_PACKET_S.src_node, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.network+2
- cmp word ptr es:[si].IPX_PACKET_S.src_network+2, ax
- jne listen10_esr
- mov ax, _Our_Address.ADDRESS_S.network
- cmp word ptr es:[si].IPX_PACKET_S.src_network, ax
- jne listen10_esr
- listen_again_buckwheat:
- mov bx, 4 ; BX = IPX Listen For Packet command
- call dword ptr IPX_Vector ; Call the IPX function
- ret
- ; * See if we need to set the done flag
- listen10_esr:
- mov ax, es:[si].IPX_PACKET_S.packet_length ; Change format
- xchg ah, al
- sub ax, es:[si].IPX_PACKET_S.size_hdr
- mov es:[si].IPX_PACKET_S.packet_length, ax
-
- lds bx, es:[si].IPX_PACKET_S.done_flag ; DS:BX -> process done flag
- mov cl, es:[si].IPX_PACKET_S.completion_code
- mov ax, ds
- or ax, bx
- jz listen20_esr
- mov [bx], cl
- mov word ptr es:[si].IPX_PACKET_S.done_flag, 0
- mov word ptr es:[si].IPX_PACKET_S.done_flag+2, 0
- ; * Check whether the packet goes in the error list or the free list
- listen20_esr:
- lds bx, es:[si].IPX_PACKET_S.parent ; DS:BX -> parent structure
- or cl, cl ; See if we got a reception error
- jz listen40_esr ; Jump if we have an unimpaired reception
- ; * Here's where we take care of our datistically challenged packets
- add word ptr [bx].XPX_STREAM_S.total_errors, 1
- adc word ptr [bx].XPX_STREAM_S.total_errors+2, 0
- inc [bx].XPX_STREAM_S.error_count
- mov cx, word ptr [bx].XPX_STREAM_S.last_error ; DX:CX->last error
- mov dx, word ptr [bx].XPX_STREAM_S.last_error+2
- mov word ptr [bx].XPX_STREAM_S.last_error, si ; Set new last error
- mov word ptr [bx].XPX_STREAM_S.last_error+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
- mov ax, dx ; See if we are the only packet here
- or ax, cx
- jnz @F ; Skip out of this ESR if we are not alone
- mov word ptr [bx].XPX_STREAM_S.first_error, si ;Set new first error
- mov word ptr [bx].XPX_STREAM_S.first_error+2, es
- ret
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
- ; * Here's where we process the good transmissions
- listen40_esr:
- push ds ; DX:CX -> the first stream structure
- mov ax, @Data
- mov ds, ax
- mov cx, word ptr _First_Stream
- mov dx, word ptr _First_Stream+2
- pop ds
- mov Last_Broad_Ptr, 0
- mov Last_Broad_Ptr+2, 0
- listen50_esr:
- cmp [bx].XPX_STREAM_S.total_listeners, 0 ; See if READ ONLY stream
- jz not_parent ; Skip this one if it is READ ONLY
- mov ax, word ptr [bx].XPX_STREAM_S.dest_node
- and ax, word ptr [bx].XPX_STREAM_S.dest_node+2
- and ax, word ptr [bx].XPX_STREAM_S.dest_node+4
- inc ax
- jnz @F ; Skip if it is not a broadcast type
- mov Last_Broad_Ptr, bx ; Save this for later
- mov Last_Broad_Ptr+2, ds
- jmp short not_parent ; Still not necessarily the right one
- @@: mov ax, word ptr [bx].XPX_STREAM_S.local_target+4 ; Match parent
- cmp word ptr es:[si].IPX_PACKET_S.src_node+4, ax
- jne not_parent
- mov ax, word ptr [bx].XPX_STREAM_S.local_target+2
- cmp word ptr es:[si].IPX_PACKET_S.src_node+2, ax
- jne not_parent
- mov ax, word ptr [bx].XPX_STREAM_S.local_target
- cmp word ptr es:[si].IPX_PACKET_S.src_node, ax
- jne not_parent
- mov ax, word ptr es:[si].IPX_PACKET_S.src_network+2
- cmp word ptr es:[si].IPX_PACKET_S.dest_network+2, ax
- jne not_parent
- mov ax, word ptr es:[si].IPX_PACKET_S.src_network
- cmp word ptr es:[si].IPX_PACKET_S.dest_network, ax
- je found_listener
- ; * At this point, the current structure has been determined not to be suitable
- not_parent:
- mov ax, cx ; See if we are at the end of our rope
- or ax, dx
- jz no_listener ; No stream match found
-
- mov ds, dx ; DS:BX -> next stream definition
- mov bx, cx
- mov cx, word ptr [bx].XPX_STREAM_S.next ; DX:CX -> next stream
- mov dx, word ptr [bx].XPX_STREAM_S.next+2
- jmp listen50_esr ; Loop until we poop
- ; * Stream ID matches up with destination address, so add packet to stream list
- found_listener:
- add word ptr [bx].XPX_STREAM_S.total_receptions, 1
- adc word ptr [bx].XPX_STREAM_S.total_receptions+2, 0
- inc [bx].XPX_STREAM_S.unread_count
- mov ax, [bx].XPX_STREAM_S.unread_count ; Update our statistics
- cmp [bx].XPX_STREAM_S.maximum_unread, ax
- jnc found10_listener ; Skip if no need to update
- mov [bx].XPX_STREAM_S.maximum_unread, ax
- found10_listener:
- mov cx, word ptr [bx].XPX_STREAM_S.last_unread
- mov dx, word ptr [bx].XPX_STREAM_S.last_unread+2
- mov word ptr [bx].XPX_STREAM_S.last_unread, si
- mov word ptr [bx].XPX_STREAM_S.last_unread+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F ; All done if there are others
- mov word ptr [bx].XPX_STREAM_S.first_unread, si
- mov word ptr [bx].XPX_STREAM_S.first_unread+2, es
- ret
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
- ; * At this point, packet is an orphan and must be sent off to farm or be glue
- no_listener:
- lds bx, dword ptr Last_Broad_Ptr ; DS:BX->last broadcast stream
- mov ax, ds
- or ax, bx
- jnz found_listener ; If one was found, use as last resort
- cmp _Ignore_Nomatch, al ; Ignore orphans or adopt
- jmp listen_again_buckwheat ; Put back on the mountaintop
- no10_listener:
- mov ax, @Data ; DS = our most lovable data segment
- mov ds, ax
- inc _Total_Nomatchs
- mov cx, word ptr _Last_Nomatch ; DX:CX -> last error packet
- mov dx, word ptr _Last_Nomatch+2
- mov word ptr _Last_Nomatch, si ; Make it point to us
- mov word ptr _Last_Nomatch+2, es
- mov word ptr es:[si].IPX_PACKET_S.next_sibling, 0
- mov word ptr es:[si].IPX_PACKET_S.next_sibling+2, 0
- mov ax, cx ; See if we need to do the first as well
- or ax, dx
- jnz @F ; All done if there are others
- mov word ptr _First_Nomatch, si ; Set us as the new first error
- mov word ptr _First_Nomatch+2, es
- ret
- @@: mov ds, dx ; DS:BX -> the first born
- mov bx, cx
- mov word ptr [bx].IPX_PACKET_S.next_sibling, si
- mov word ptr [bx].IPX_PACKET_S.next_sibling+2, es
- ret
- listen_esr endp
- end
-
-
-
- [LISTING TWO]
-
- ; ****************************************************************************
- ; * Title: XPX_INIT.ASM -- Rahner James
- ; * Copyright (c) December 1991, Ryu Consulting, 916/722-1939
- ; * File contains all the functions to support initializing IPX engine
- ; ****************************************************************************
-
- _XPX_INIT_ASM_ equ 1
- include network.inc
- .data
- public IPX_Vector, _Socket_Life, _SPX_Version, _SPX_Max_Connections,
- _Our_Address
- public _SPX_Available_Connections, _SPX_Retry_Count
-
- IPX_Vector dw offset dummy_IPX_function,@Code ; -> IPX support function
- _Socket_Life db 0 ; 0=socket closed at app termination
- ; 0ffh= socket closed when requested
- _SPX_Version dw 0 ; SPX version #: MSByte=major, LSByte=minor
- _SPX_Max_Connections dw 0 ; Max number of SPX connections
- _SPX_Available_Connections dw 0 ; # of SPX connections available to app
- _SPX_Retry_Count db 0 ; Retry count for SPX establish connection
- _SPX_Bowser_Flag db 1 ; Watchdog flag, 0=disable, 1=enable
- _Our_Address label dword ; Global access for this structure
- network dd 0 ; Network address
- node db 6 dup(0) ; Node address
- socket dw 0 ; Socket number
-
- .code
- ; ****************************************************************************
- ; * int XPX_INIT( us SOCKET_NUMBER ) -- Initializes all IPX/SPX internals
- ; * Given: SOCKET_NUMBER = socket number to open for listening, 0 opens
- ; * the next available
- ; * Returns: 0 if IPX was initialized successfully
- ; * -1 = socket already open (!)
- ; * -2 = socket table full
- ; * -3 = IPX or SPX is not installed
- ; * Note: Initializes IPX vector, opens a listening socket for IPX driver.
- ; * Internal vectors, counter, & pointers are brought to initial conditions
- ; ****************************************************************************
- xpx_init proc uses di si, socket_number:word
- mov ax, 7a00h ; Get the IPX vector
- int 2fh ; Query the DOS multiplexer
- inc al ; AL = 0ffh if IPX is there
- jnz derr_xpx_init ; Quit in disgrace if it's not there
- mov IPX_Vector, di ; IPX function vector returned in ES:DI
- mov IPX_Vector+2, es
- ; * See if we need to close the old stuff down
- mov dx, socket
- or dx, dx ; See if we opened a socket
- jz xpx10_init ; Skip if we didn't
- cmp socket_number, 0
- jz xpx20_init ; Skip if so
- cmp socket_number, dx ; See if it's the same as before
- je xpx20_init ; Skip if it is
- IPX 1 ; IPX Close Socket command
- ; * Now, open the socket
- xpx10_init:
- mov dx, socket_number
- mov al, _Socket_Life
- IPX_CHECK 0 ; IPX Open Socket command
- jnz done_xpx_init ; Quit if an error
- xpx20_init:
- mov socket, dx
- ; * Get our internetwork address
- mov ax, ds ; ES = DS
- mov es, ax
- mov si, offset network
- mov di, si
- IPX 9 ; IPX Get Internetwork Address command
- ; * Last, we have to initialize the SPX interface
- xor ax, ax
- IPX_CHECK 10h ; SPX Initialize command
- jz derr_xpx_init ; Quit if it's not there
- mov _SPX_Version, bx ; Save the information returned
- mov _SPX_Max_Connections, cx
- mov _SPX_Available_Connections, dx
- xor ax, ax ; Good return
- jmp short done_xpx_init
- derr_xpx_init:
- mov al, -3 ; It's gone McCreedy!
- done_xpx_init:
- cbw
- ret
- xpx_init endp
-
- ; ****************************************************************************
- ; * int DUMMY_IPX_FUNCTION( void ) -- Dummy function that returns error
- ; * code -10 so that system will not hang if not initialized
- ; * Given: nothing
- ; * Returns: -10 always
- ; ****************************************************************************
- dummy_IPX_function proc far
- mov ax, -10
- ret
- dummy_IPX_function endp
- end
-
-
-
- Example 1:
-
- mov ax, 7a00h ; Function 7Ah, AL = 0
- int 2fh ; MS-DOS Multiplex interrupt
- ; Returns with AL == 0FFh if xPX
- ; exists and ES:DI == xPX vector
-
- inc al ; Set ZERO if AL == -1
- jnz outta_here ; Quit if xPX isn't around
- mov IPX_Vector, di ; Save the xPX entry vector
- mov IPX_Vector+2, es
-